/**
 * 
 */
package com.qolome.utils;

import java.nio.charset.StandardCharsets;
import java.security.GeneralSecurityException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

/**
 * @Description:Hash工具类
 * @author 姜锋
 * @date 2020年1月5日 上午9:41:38 
 * @version V1.0   
 *
 */
public class HashUtil {

	/**
	 * Generate SHA-1 as hex string (all lower-case).
	 *
	 * @param input Input as string.
	 * @return Hex string.
	 */
	public static String sha1(String input) {
		return sha1(input.getBytes(StandardCharsets.UTF_8));
	}

	/**
	 * Generate SHA-1 as hex string (all lower-case).
	 *
	 * @param input Input as bytes.
	 * @return Hex string.
	 */
	public static String sha1(byte[] input) {
		MessageDigest md = null;
		try {
			md = MessageDigest.getInstance("SHA1");
		} catch (NoSuchAlgorithmException e) {
			throw new RuntimeException(e);
		}
		md.update(input);
		byte[] digest = md.digest();
		return ByteUtil.toHexString(digest);
	}

	public static byte[] sha1AsBytes(String input) {
		return sha1AsBytes(input.getBytes(StandardCharsets.UTF_8));
	}

	/**
	 * Generate SHA-1 as bytes.
	 *
	 * @param input Input as bytes.
	 * @return Bytes.
	 */
	public static byte[] sha1AsBytes(byte[] input) {
		MessageDigest md = null;
		try {
			md = MessageDigest.getInstance("SHA1");
		} catch (NoSuchAlgorithmException e) {
			throw new RuntimeException(e);
		}
		md.update(input);
		return md.digest();
	}

	/**
	 * Generate SHA-256 as hex string (all lower-case).
	 *
	 * @param input Input as String.
	 * @return Hex string.
	 */
	public static String sha256(String input) {
		return sha256(input.getBytes(StandardCharsets.UTF_8));
	}

	/**
	 * Generate SHA-256 as hex string (all lower-case).
	 *
	 * @param input Input as String.
	 * @return Hex string.
	 */
	public static byte[] sha256AsBytes(String input) {
		return sha256AsBytes(input.getBytes(StandardCharsets.UTF_8));
	}

	/**
	 * Generate SHA-256 as hex string (all lower-case).
	 *
	 * @param input Input as bytes.
	 * @return Hex string.
	 */
	public static String sha256(byte[] input) {
		MessageDigest md = null;
		try {
			md = MessageDigest.getInstance("SHA-256");
		} catch (NoSuchAlgorithmException e) {
			throw new RuntimeException(e);
		}
		md.update(input);
		byte[] digest = md.digest();
		return ByteUtil.toHexString(digest);
	}

	/**
	 * Generate SHA-256 as bytes.
	 *
	 * @param input Input as bytes.
	 * @return SHA bytes.
	 */
	public static byte[] sha256AsBytes(byte[] input) {
		MessageDigest md = null;
		try {
			md = MessageDigest.getInstance("SHA-256");
		} catch (NoSuchAlgorithmException e) {
			throw new RuntimeException(e);
		}
		md.update(input);
		return md.digest();
	}

	/**
	 * Generate SHA-512 as bytes.
	 *
	 * @param input Input as bytes.
	 * @return SHA bytes.
	 */
	public static byte[] sha512AsBytes(byte[] input) {
		MessageDigest md = null;
		try {
			md = MessageDigest.getInstance("SHA-512");
		} catch (NoSuchAlgorithmException e) {
			throw new RuntimeException(e);
		}
		md.update(input);
		return md.digest();
	}

	/**
	 * Do HMAC-SHA256.
	 *
	 * @return Hex string.
	 */
	public static byte[] hmacSha256AsBytes(byte[] data, byte[] key) {
		SecretKey skey = new SecretKeySpec(key, "HmacSHA256");
		Mac mac;
		try {
			mac = Mac.getInstance("HmacSHA256");
			mac.init(skey);
		} catch (GeneralSecurityException e) {
			throw new RuntimeException(e);
		}
		mac.update(data);
		return mac.doFinal();
	}

	/**
	 * Do HMAC-SHA256.
	 *
	 * @return Hex string.
	 */
	public static String hmacSha256(byte[] data, byte[] key) {
		return ByteUtil.toHexString(hmacSha256AsBytes(data, key));
	}

	/**
	 * Do HMAC-SHA1.
	 *
	 * @return byte[] as result.
	 */
	public static byte[] hmacSha1(byte[] data, byte[] key) {
		SecretKey skey = new SecretKeySpec(key, "HmacSHA1");
		Mac mac;
		try {
			mac = Mac.getInstance("HmacSHA1");
			mac.init(skey);
		} catch (GeneralSecurityException e) {
			throw new RuntimeException(e);
		}
		mac.update(data);
		return mac.doFinal();
	}

	/**
	 * Do HMAC-SHA256.
	 *
	 * @return byte[] as result.
	 */
	public static String hmacSha256(String data, String key) {
		return hmacSha256(data.getBytes(StandardCharsets.UTF_8), key.getBytes(StandardCharsets.UTF_8));
	}

	/**
	 * Do HMAC-SHA256.
	 *
	 * @return byte[] as result.
	 */
	public static byte[] hmacSha256AsBytes(String data, String key) {
		return hmacSha256AsBytes(data.getBytes(StandardCharsets.UTF_8), key.getBytes(StandardCharsets.UTF_8));
	}

	/**
	 * Do HMAC-SHA256.
	 *
	 * @return byte[] as result.
	 */
	public static String hmacSha256(byte[] data, String key) {
		return hmacSha256(data, key.getBytes(StandardCharsets.UTF_8));
	}
	
	
	public static String getMd5(String content) {
		try {
			// 创建加密对象
			MessageDigest digest = MessageDigest.getInstance("md5");

			// 调用加密对象的方法，加密的动作已经完成
			byte[] bs = digest.digest(content.getBytes());
			// 接下来，我们要对加密后的结果，进行优化，按照mysql的优化思路走
			// mysql的优化思路：
			// 第一步，将数据全部转换成正数：
			String hexString = "";
			for (byte b : bs) {
				// 第一步，将数据全部转换成正数：
				// 解释：为什么采用b&255
				/*
				 * b:它本来是一个byte类型的数据(1个字节) 255：是一个int类型的数据(4个字节)
				 * byte类型的数据与int类型的数据进行运算，会自动类型提升为int类型 eg: b: 1001 1100(原始数据)
				 * 运算时： b: 0000 0000 0000 0000 0000 0000 1001 1100 255: 0000
				 * 0000 0000 0000 0000 0000 1111 1111 结果：0000 0000 0000 0000
				 * 0000 0000 1001 1100 此时的temp是一个int类型的整数
				 */
				int temp = b & 255;
				// 第二步，将所有的数据转换成16进制的形式
				// 注意：转换的时候注意if正数>=0&&<16，那么如果使用Integer.toHexString()，可能会造成缺少位数
				// 因此，需要对temp进行判断
				if (temp < 16 && temp >= 0) {
					// 手动补上一个“0”
					hexString = hexString + "0" + Integer.toHexString(temp);
				} else {
					hexString = hexString + Integer.toHexString(temp);
				}
			}
			return hexString;
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		}
		return "";
	}
}